Parameters Modifiers / Passing Modifiers / Argument Passing Modifiers

  • Default C# behavior is "passed-by-value".

  • These modifiers change that behavior.

ref

  • Pass the variable by reference and allow modification.

  • No copy is made.

  • Example:

    void AddOne(ref int x)
    {
        x += 1;
    }
    
    int value = 5;
    AddOne(ref value);
    
    • After call:

    value == 6
    

ref  return

  • Functions can return references.

  • No copies occur.

  • Example:

    ref int Find(int[] arr, int index)
    {
        return ref arr[index];
    }
    
    int[] data = {1,2,3};
    
    ref int v = ref Find(data, 1);
    v = 10;
    
    • Array becomes:

    [1,10,3]
    

ref  local

ref int element = ref array[5];
element++;
  • This modifies the array element directly.

ref struct

  • Used for stack-only types.

  • Restrictions:

    • cannot be boxed

    • cannot live on heap

    • cannot be captured by lambdas

  • Examples:

    • Span<T>  is a ref struct .

ref struct BufferView
{
    Span<byte> data;
}

out

  • Pass-by-reference, just like ref , but guarantees assignment inside the function.

  • The caller does not  need to initialize the variable.

  • Example:

    void GetValues(out int a, out int b)
    {
        a = 10;
        b = 20;
    }
    
    int x;
    int y;
    
    GetValues(out x, out y);
    
    • After call:

    x = 10
    y = 20
    

in

  • Passes by reference but read-only.

  • Useful for large structs.

struct Vec3
{
    public float x, y, z;
}

float Length(in Vec3 v)
{
    return MathF.Sqrt(v.x*v.x + v.y*v.y + v.z*v.z);
}
  • Avoids copying the struct.